import { deepFullCopy, messages } from "share/common";
import React from "react";
import { Upload, Icon, message, Modal, Button, Row, Col, Popconfirm, Popover, Progress } from "antd";
import config from "config";
import FileViewer from "components/file-viewer";
import "styles/components/file-upload.scss";
import { connect } from "react-redux";
import excelImage from "images/file-type/excel.png";
import pdfImage from "images/file-type/pdf.png";
import pptImage from "images/file-type/ppt.png";
import txtImage from "images/file-type/txt.png";
import wordImage from "images/file-type/word.png";
import unknownImage from "images/file-type/unknown.png";
import ofdImage from "images/file-type/ofd.png";
import constants from "share/constants";
import baseService from "share/base.service";
import { handleUploadOptions } from "share/utils";

/**
 * 图片上传组件
 */
export class FileUpload_noUse extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      previewVisible: false,
      previewImage: "",
      fileList: [],
      result: [],
      previewIndex: 0, //预览图片的index
      modalShow: false,
      info: null,
      attachmentTypes: "",
      acceptTypes: "", //当配置了isShowExtraPrompt，accept取安全平台返回的类型
    };
  }

  componentDidMount() {
    const { isShowExtraPrompt } = this.props;
    if (this.props.defaultFileList.splice) {
      this.showDefaultFileList(this.props.defaultFileList);
    }
    if (isShowExtraPrompt) {
      this.initExtraPrompt();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.isShowDefault) {
      //defaultFileList的变化会中断现有的uploading文件继续上传
      if (
        nextProps.defaultFileList.splice &&
        !nextProps.defaultFileList.filter((i) => i.status && i.status !== "done").length
      ) {
        this.showDefaultFileList(nextProps.defaultFileList);
      }
    }
  }

  initExtraPrompt = () => {
    baseService.getAttachmentType().then((res) => {
      let types = res.data.formats || [];
      let acceptTypes = [];
      types.forEach((type) => {
        acceptTypes.push("." + type);
      });
      this.setState({
        attachmentTypes: res.data.formats.join("/"),
        acceptTypes: acceptTypes.join(","),
      });
    });
  };

  //为了显示默认已经上传的图片
  showDefaultFileList = (defaultFileList) => {
    const thumbUrl = (name) => {
      if (name.match(/.ofd$/)) return ofdImage;
      if (name.match(/.pdf$/)) return pdfImage;
    };
    let fileList = [];
    defaultFileList.map((attachment) => {
      fileList.push({
        uid: attachment.attachmentOID,
        name: attachment.fileName,
        status: "done",
        url: attachment.fileURL,
        thumbUrl: thumbUrl(attachment.fileName),
        fileName: attachment.fileName,
        fileURL: attachment.fileURL,
        attachmentOID: attachment.attachmentOID,
      });
    });
    this.setState({ fileList, result: defaultFileList });
  };

  handleData = () => {
    return this.props.data ? this.props.data : { attachmentType: this.props.attachmentType };
  };

  handleChange = (info) => {
    let { result, fileList } = this.state;
    const { showInExpenseDetail, type, fileType, accept } = this.props;
    const status = info.file.status;
    console.log("handleChange", info, this.props.fileSize);
    if (fileType) {
      //控制上传图片的类型
      let isFileType = false;
      let acceptList = accept.split(",");
      fileType.map((type) => {
        if (
          info.file.type === `image/${type}` ||
          acceptList.includes(info.file.type) ||
          (acceptList.includes(".ofd") && info.file.name.match(/.ofd$/))
        ) {
          isFileType = true;
        }
      });
      if (!isFileType && info.file.status !== "removed") {
        //上传失败，图片格式错误
        const errorMsg =
          type === "image" ? messages("common-1.key72") /*上传失败，文件格式错误*/ : messages("common-1.key57");
        /*上传失败，图片格式错误*/
        message.error(errorMsg);
        return;
      }
    }
    if (this.props.fileSize) {
      //控制上传图片的大小
      const isLtSize = info.file.size / 1024 / 1024 <= this.props.fileSize;
      if (!isLtSize && info.file.status !== "removed") {
        //您上传的附件已超出大小限制，请重新上传！
        message.error(
          messages("common-1.key58", {
            arg1: info.file.name,
            arg2: this.props.fileSize,
          }) /*{arg1}大于{arg2}M*/
        );
        return;
      }
    }
    this.props.isUploading(true);
    if (status === "error") {
      message.error(
        `${info.file.name} ${messages("common-1.key59") /*上传失败*/} ${
          info.file.response ? info.file.response.message : ""
        }`
      );
    }

    if (status === "done") {
      result.push(info.file.response);
      message.success(`${info.file.name} ${messages("common-1.key60") /*上传成功*/}`);
    }

    if (fileList.length !== info.fileList.length || status === "done" || status === "error") {
      this.props.isUploading(false);
      if (showInExpenseDetail) {
        this.props.onChange(result.concat(info.fileList.filter((i) => i.status === "uploading")));
      } else {
        this.props.onChange(result);
      }
    }
    let fileListCopy = deepFullCopy(info.fileList.filter((i) => i.status !== "error"));
    fileListCopy.map((file) => {
      if (file.type === "application/pdf") {
        file.thumbUrl = pdfImage;
        file.url = info.file.response ? info.file.response.fileURL : file.thumbUrl;
      } else if (file.name.match(/.ofd$/)) {
        file.thumbUrl = ofdImage;
        file.url = info.file.response ? info.file.response.fileURL : file.thumbUrl;
      } else if (file.thumbUrl) {
        file.url = file.thumbUrl;
      }
    });
    this.setState({ fileList: fileListCopy, result });
  };

  // 预览
  handlePreview = (file) => {
    let { isPreViewCallBack, handlePreViewCallBack } = this.props;
    if (isPreViewCallBack) {
      handlePreViewCallBack(file);
      return;
    }
    let size = file.size;
    if ((this.isAllowedFile(file) && size && size < 10 * 1024 * 1024) || !size) {
      this.state.result.map((item, index) => {
        if (item.attachmentOID === (file.response ? file.response.attachmentOID : file.attachmentOID)) {
          this.setState({
            previewIndex: index,
            previewVisible: true,
          });
        }
      });
    } else {
      window.open(file.response ? file.response.fileURL : file.fileURL, "_blank");
    }
  };

  getExtension = (file) => {
    let fileName =
      file.fileName || file.name || (file.response ? file.response.fileName || file.response.name || "" : "");
    let sections = fileName.split(".");
    let extension = sections[sections.length - 1].toLowerCase();
    return extension.length > 3 ? extension.substring(0, 4) : extension;
  };

  getImage = (file) => {
    let extension = this.getExtension(file);
    let imageExtension = ["png", "gif", "jpg", "jpeg", "bmp"];
    let wordExtension = ["doc", "docx"];
    let pptExtension = ["ppt", "pptx"];
    let excelExtension = ["xls", "xlsx"];
    let txtExtension = ["txt"];
    let pdfExtension = ["pdf"];
    if (imageExtension.has(extension))
      return (
        file.thumbnailUrl || file.fileURL || (file.response ? file.response.thumbnailUrl || file.response.fileURL : "")
      );
    if (wordExtension.has(extension)) return wordImage;
    if (pptExtension.has(extension)) return pptImage;
    if (excelExtension.has(extension)) return excelImage;
    if (txtExtension.has(extension)) return txtImage;
    if (pdfExtension.has(extension)) return pdfImage;
    return unknownImage;
  };

  isAllowedFile = (file) => {
    let extension = this.getExtension(file);
    let imageExtension = [
      "png",
      "gif",
      "jpg",
      "jpeg",
      "bmp",
      "doc",
      "docx",
      "ppt",
      "pptx",
      "xls",
      "xlsx",
      "txt",
      "pdf",
      "ofd",
    ];
    return imageExtension.has(extension);
  };

  closeModal = () => {
    this.setState({ modalShow: false });
  };

  deleteImage = (e, attachmentOID) => {
    e.stopPropagation();
    let { result, info, fileList } = this.state;
    const { showInExpenseDetail } = this.props;
    let fileListCopy = deepFullCopy(fileList);
    let required = false;
    let attachmentOid = info
      ? info.attachmentOID ||
        (info.response
          ? info.response.attachmentOID ||
            (info.response.attachmentDTO ? info.response.attachmentDTO.attachmentOID : null)
          : null)
      : attachmentOID;
    if (!attachmentOid) required = true;
    let currentResultIndex = -1;
    result.map((item, index) => {
      if (item.attachmentOID === attachmentOid || (info && item.attachmentOID === info.uid)) {
        required = this.props.handleDelete(item.id);
        currentResultIndex = index;
      }
    });
    if (required) {
      let currentFileIndex = -1;
      fileListCopy.map((file, index) => {
        (file.attachmentOID === attachmentOid ||
          (file.response && file.response.attachmentOID === attachmentOid) ||
          (info && file.uid === info.uid)) &&
          (currentFileIndex = index);
      });
      result.splice(currentResultIndex, 1);
      currentFileIndex > -1 && fileListCopy.splice(currentFileIndex, 1);
    }
    this.setState({
      result,
      info: null,
      modalShow: false,
      fileList: fileListCopy,
    });
    if (showInExpenseDetail) {
      this.props.onChange(result.concat(fileListCopy.filter((i) => i.status === "uploading")));
    } else {
      this.props.onChange(result);
    }
  };

  beforeUpload = (file, fileList) => {
    let { fileSize, beforeUpload } = this.props;
    let size = file.size;
    let result = true;
    if (beforeUpload) {
      result = beforeUpload();
    }
    if (size > fileSize * 1024 * 1024) {
      result = false;
    }
    return result;
  };

  remove = (info) => {
    this.setState({ modalShow: true, info: info });
    return false;
  };

  render() {
    const { previewVisible, fileList, previewIndex, result, modalShow, attachmentTypes, acceptTypes } = this.state;
    const {
      type,
      disabled,
      isShowExtraPrompt,
      placeHolder,
      isNeedLayout,
      accept,
      showInExpenseDetail,
      showUpload,
      approveHistoryShowFileName,
      canRemove,
      className,
      style,
    } = this.props;
    const uploadButton =
      type === "image" ? (
        <div>
          <Icon type="plus" style={{ fontSize: 32, color: "#999" }} />
          <div className="ant-upload-text" style={{ marginTop: 8, color: "#666" }}>
            {messages("common.upload") /*上传*/}
          </div>
        </div>
      ) : (
        <Button>
          <Icon type="upload" /> {messages("common.upload") /*上传*/}
        </Button>
      );
    const upload_headers = {
      Authorization: "Bearer " + this.props.authToken.access_token,
    };
    let [uploadHeaders, uploadUrl] = handleUploadOptions(upload_headers, this.props.uploadUrl);

    let size = this.props.fileSize ? this.props.fileSize : 10;
    let isDingTalkSSO = sessionStorage.getItem("isDingTalkSSO");
    let isWechatSSO = sessionStorage.getItem("isWechatSSO");
    let acceptProps =
      isDingTalkSSO === "true" || isWechatSSO === "true"
        ? {}
        : isShowExtraPrompt && acceptTypes
        ? { accept: acceptTypes }
        : { accept };
    let formLayout = isNeedLayout
      ? {
          xs: { span: 8 },
          sm: { span: 8 },
          md: { span: 6 },
          lg: { span: 5 },
          xl: { span: 4 },
          xxl: { span: 3 },
        }
      : { span: 12 };
    return (
      <div className={`file-upload ${className}`} style={style}>
        {showUpload && (
          <div>
            <Upload
              {...acceptProps}
              name="file"
              data={this.handleData}
              action={uploadUrl}
              beforeUpload={this.beforeUpload}
              headers={uploadHeaders}
              fileList={this.props.showFileName ? fileList : []}
              showUploadList={showInExpenseDetail ? false : { showRemoveIcon: !this.props.disabled }}
              onPreview={this.handlePreview}
              onChange={this.handleChange}
              onRemove={this.remove}
            >
              {fileList.length >= this.props.maxNum || this.props.disabled ? null : uploadButton}
            </Upload>
            {this.props.showMaxNum && !this.props.disabled && (
              <span className="file-upload-max-size">
                (
                {
                  messages("common.max.upload.attachment", {
                    arg1: this.props.maxNum,
                  }) /*最多上传 {arg1} 个附件*/
                }
                )
              </span>
            )}
          </div>
        )}
        {!disabled && (
          <div className="file-upload-accept">
            {isShowExtraPrompt && (
              <div className="flex-box">
                <div className={"accept-line"}>
                  {messages("common-1.key703") /*支持格式*/}：{attachmentTypes}
                </div>
                <div className={"popover-tip"}>
                  <Popover content={attachmentTypes} placement={"topLeft"}>
                    {messages("common.all") /*全部*/}
                    <Icon type="exclamation-circle-o" />
                  </Popover>
                </div>
              </div>
            )}
            {placeHolder && `${placeHolder}，`}
            {messages("common-1.key1336", { arg1: size }) /*单个小于{arg1}M*/}
          </div>
        )}
        <Row type="flex" gutter={8}>
          {fileList.map((attachment, index) => {
            return showInExpenseDetail ? (
              <Col className="file-upload-preview-box" key={index} {...formLayout}>
                {attachment.status === "uploading" ? (
                  <div className="file-upload-preview" style={{ backgroundColor: "#F7F8FA" }}>
                    <Progress percent={Math.min(attachment.percent || 0, 99)} size="small" showInfo={false} />
                    <p style={{ lineHeight: "14px" }}>{messages("common-1.key62") /*文件上传中...*/}</p>
                  </div>
                ) : (
                  <div
                    className="file-upload-preview file-upload-preview-list"
                    onClick={(e) => this.handlePreview(attachment)}
                  >
                    <img src={this.getImage(attachment)} />
                    <Popover placement="topLeft" content={attachment.fileName || attachment.name}>
                      <span className="file-upload-title" onClick={() => this.handlePreview(attachment)}>
                        {attachment.fileName || attachment.name}
                      </span>
                    </Popover>
                    {!disabled && (canRemove ? canRemove(attachment) : true) && (
                      <Popconfirm
                        title={messages("common-1.key63") /*确定删除该附件吗*/ + "？"}
                        onConfirm={(e) =>
                          this.deleteImage(e, attachment.attachmentOID || attachment.response.attachmentOID)
                        }
                        okText={messages("common.ok") /*确定*/}
                        cancelText={messages("common.cancel") /*取消*/}
                      >
                        <Icon
                          type="delete"
                          className="file-upload-icon"
                          onClick={(e) => {
                            e.stopPropagation();
                          }}
                        />
                      </Popconfirm>
                    )}
                  </div>
                )}
              </Col>
            ) : (
              <Col className="attachment-block" key={index} onClick={() => this.handlePreview(attachment)}>
                <img src={this.getImage(attachment)} />
                {approveHistoryShowFileName && <span className="attachment-block-name">{attachment.fileName}</span>}
              </Col>
            );
          })}
        </Row>
        <FileViewer
          visible={previewVisible}
          attachments={result}
          defaultIndex={previewIndex}
          onCancel={() => this.setState({ previewVisible: false })}
          urlKey="fileURL"
          valueKey="attachmentOID"
        />
        <Modal
          onOk={this.deleteImage}
          onCancel={this.closeModal}
          okText={messages("common.ok") /*确定*/}
          cancelText={messages("common.cancel") /*取消*/}
          visible={modalShow}
          title={messages("common-1.key64") /*操作提醒*/}
        >
          <p
            style={{
              textAlign: "center",
              fontSize: "20px",
              margin: "10px 0px",
            }}
          >
            {messages("common-1.key65") /*您确定删除该附件?*/}
          </p>
        </Modal>
      </div>
    );
  }
}

FileUpload_noUse.propTypes = {
  type: React.PropTypes.bool, //组件支持的类型，['file', 'image']
  uploadUrl: React.PropTypes.string, //上传URL
  attachmentType: React.PropTypes.string.isRequired, //附件类型
  defaultFileList: React.PropTypes.array, //默认上传的文件列表
  onChange: React.PropTypes.func, //上传成功后的回调
  maxNum: React.PropTypes.number, //最大上传文件的数量
  placeHolder: React.PropTypes.string, //控件配置的提示文案
  fileType: React.PropTypes.array, //上传文件的类型
  fileSize: React.PropTypes.number, //上传文件的大小
  isShowDefault: React.PropTypes.bool, //是否要进行回显，是否一直允许从父组件接受变化的图片列表
  disabled: React.PropTypes.bool, //是否禁用
  showMaxNum: React.PropTypes.bool, //是否显示最多上传多少图片
  data: React.PropTypes.object, //上传接口的参数
  handleDelete: React.PropTypes.func, //删除附件的回调
  showFileName: React.PropTypes.bool, // 是否显示文件列表名称
  isPreViewCallBack: React.PropTypes.bool, // 附件是否预览回调
  handlePreViewCallBack: React.PropTypes.func, //附件预览回调
  accept: React.PropTypes.string, //附件只接受选择的类型
  isShowExtraPrompt: React.PropTypes.bool, //是否展示安全配置中支持上传的附件类型文案
  isUploading: React.PropTypes.func, //附件是否正在上传中
  showUpload: React.PropTypes.bool,
  isNeedLayout: React.PropTypes.bool,
  showInExpenseDetail: React.PropTypes.bool, //业务参数 控制样式以及是否抛出仍在上传中的附件，为否时只抛出以上传成功的，参考bug:60380
  approveHistoryShowFileName: React.PropTypes.bool, //业务参数，审批流中附件显示姓名是不同的样式
};

FileUpload_noUse.defaultProps = {
  type: "file",
  uploadUrl: `${config.baseUrl}/api/upload/attachment`,
  defaultFileList: [],
  onChange: () => {},
  maxNum: 9,
  placeHolder: "",
  isShowDefault: false,
  disabled: false,
  showMaxNum: false,
  isPreViewCallBack: false,
  showUpload: true,
  isNeedLayout: false,
  handleDelete: () => {
    return true;
  },
  showFileName: true,
  accept: constants.acceptFileTypes,
  isShowExtraPrompt: false,
  showInExpenseDetail: false,
  isUploading: () => {},
  approveHistoryShowFileName: false,
};

function mapStateToProps(state) {
  return {
    authToken: state.main.authToken,
  };
}

// 注意
// defaultFileList里面的对象属性要有
//   attachmentOID,
//   fileName,
//   fileURL

export default connect(mapStateToProps)(FileUpload_noUse);
